//
// Created by F1997 on 2025/3/11.
//

#include "SocketUtils.h"
#include "../decode/shfe_decode.h"

namespace ntp {

#define MAX_EVENTS 10

    // https://blog.csdn.net/qq_44913716/article/details/134674965
    int SocketUtils::readNetworkIfaceLine(std::string sectionId, std::chrono::system_clock::time_point startTime,
                                          ntp::IniReader* iniCfg, SafeQueue<MarketData>* data_queue, std::string debug) {

        // 从配置文件中获取配置
        std::string device = iniCfg->ReadString(sectionId.data(), "device","");
        std::string sourceIP = iniCfg->ReadString(sectionId.data(), "sourceIP","");
        std::string sourcePort = iniCfg->ReadString(sectionId.data(), "sourcePort","");
        std::string destinationIP = iniCfg->ReadString(sectionId.data(), "destinationIP","");
        int destinationPort = iniCfg->ReadInt(sectionId.data(), "destinationPort",-1);
        std::string filterStr = iniCfg->ReadString(sectionId.data(), "filterStr",""); // 抓包过滤条件

        std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");
        int exchange_id = iniCfg->ReadInt("MODE", "exchange_id",0);

        //std::ofstream outFile("socket_out_" + sectionId + ".csv");
        std::ofstream outFile("pcap_out_" + sectionId + ".csv");

        // ======================
        int client_fd, epoll_fd;
        client_fd = socket(PF_PACKET, SOCK_RAW/*SOCK_DGRAM*/, htons(ETH_P_ALL/*ETH_P_IP*/));
        if (client_fd < 0) {
            perror("Socket creation failed");
            return 1;
        }

        int BufferSize = 1024 * 1024 * 12;
        // 设置套接字选项的 Unix 系统调用，可以添加自定义的过滤规则
        int retSet = ::setsockopt(client_fd, SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize));
        if (retSet != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
        // 设置文件描述符为非阻塞
        int i_ret = fcntl(client_fd,F_SETFL, O_NONBLOCK);  // 设置文件描述符的状态标志
        if (i_ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
        // 绑定网卡设备，使用网卡名称
        struct ifreq stIf;
        strcpy(stIf.ifr_name, device.c_str());
        int ret = ioctl(client_fd, SIOCGIFINDEX, &stIf); // ioctl 函数允许应用程序与设备驱动程序进行通信，执行各种设备特定的操作。常见的用途包括调整终端属性、获取网络接口状态等
        if (ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }

        // 设置服务器地址
        struct sockaddr_in server_address;
        memset(&server_address, 0, sizeof(server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(destinationPort);

        struct hostent *server = gethostbyname(destinationIP.c_str());
        if (server == nullptr) {
            perror("Host lookup failed ===>");
            return 1;
        }
        memcpy(&server_address.sin_addr.s_addr, server->h_addr, server->h_length);

        // 发送数据
        //const char *message = "Hello from client"; // Hello from server = 17字节
        //sendto(client_fd, message, strlen(message), 0, (struct sockaddr *)&server_address, sizeof(server_address));

        char buffer[4096] = {0};
        int pkgCount= 0;
        while(1) {
            // 接收数据
            struct sockaddr_in server_addr;
            socklen_t server_len = sizeof(server_addr);

            // ==========
            //int valread = recvfrom(client_fd, buffer, 4096, 0, (struct sockaddr *)&server_addr, &server_len);
            //std::cout << "client_fd=" << client_fd << std::endl;
            //if (valread < 0) {
            //    perror("Read failed ===>");
            //    return 1;
            //}
            // ==========

            int valread = -1;
            fd_set readfds;
            FD_ZERO(&readfds); // 清空文件描述符集合
            FD_SET(client_fd, &readfds); // 将文件描述符添加到集合中
            struct timeval tv_out; // 设置超时时间
            tv_out.tv_sec = 0;
            tv_out.tv_usec = -1;
            int retval = select(client_fd + 1, &readfds, NULL, NULL, 0); // 如果为NULL，则select函数会一直阻塞，直到有事件发生。如果指定为0，则select函数会立即返回，用于轮询文件描述符的状态
            if (retval == -1 && errno != EINTR) {
                perror("select error===>");
                // 处理错误
            } else if (retval) {
                // 数据可读，进行recv操作
                valread = recvfrom(client_fd, buffer, 4096, 0, (struct sockaddr *)&server_addr, &server_len);
            } else {
                // 超时或其他情况处理
            }

            // 获取纳秒级时间戳
            auto now = std::chrono::high_resolution_clock::now();
            auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
                    now.time_since_epoch())
                    .count();

            struct timeval tv;
            if (valread >= 0) {
                // 获取时间戳
                if (gettimeofday(&tv, NULL) != -1) {
                    //printf("数据包的时间戳为(毫秒级): %ld.%06ld\n", tv.tv_sec, tv.tv_usec);
                    //printf("数据包的时间戳为(毫秒级): %lld\n", timestamp);
                }
            } else {
                // 错误处理
                if (errno != EAGAIN) { // try agen
                    //perror("recvfrom===>");
                    SPDLOG_LOGGER_ERROR(my_logger, "recvfrom===>: {}");
                    //break;
                }
            }
            //std::cout << "Message from server: " << strlen(buffer) << ", 字节长度: " << valread << ",pkgCount=" << pkgCount << std::endl;

            switch (exchange_id) {
                case 1: // 广期
                    // 基于时间窗口的统计 = 每3秒一个窗口，记录一次
                {
                    pkgCount++;
                }
                    break;
                case 2: // 上期
                {
                    pkgCount++;

                    MarketData marketData;
                    memset(&marketData, 0x00, sizeof(MarketData));
                    marketData.lineFlag = sectionId;
                    marketData.destinationIP = destinationIP;
                    // 包外数据

                    // 包内毫秒级时间戳
                    //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                    marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                    marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                    // 解析数据包中的数据，传递的数据尽量要少
                    //marketData.pkthdr = header; // 原始包头数据
                    //marketData.packet = packet; // 原始payload数据
                    pcap_pkthdr* pkthdr;
                    pkthdr = (pcap_pkthdr*)malloc(sizeof(pcap_pkthdr));
                    pkthdr->caplen = 0;
                    pkthdr->len = valread; // 长度
                    pkthdr->ts.tv_sec = timestamp / 1000000000;
                    pkthdr->ts.tv_usec = timestamp % 1000000000;
                    //std::cout << "pkgCount=" << pkgCount << ",tv_sec=" << pkthdr->ts.tv_sec << ",tv_usec=" << pkthdr->ts.tv_usec  << std::endl;
                    shfe_decode::parse_packet_shfe(pkthdr, reinterpret_cast<const u_char*>(buffer), marketData, outFile);

                    //struct my_ether_header *eth_hdr = (struct my_ether_header *)packet;
                    //std::cout << "eth_hdr->ether_type=" << eth_hdr->ether_type << std::endl;

                    //SPDLOG_LOGGER_INFO(my_logger,"{},packet_no={},time1={},time2={},snap_time={},snap_millisec={}",sectionId,marketData.packet_no,marketData.time1,marketData.time2,marketData.snap_time,marketData.snap_millisec);
                }
                    break;
                case 3: // 大连
                {
                    pkgCount++; // 当前接受的总包数，包数不是连续的？？？
                }
                    break;
                case 4: // 郑州
                {
                    pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                    MarketData marketData;
                    memset(&marketData, 0x00, sizeof(MarketData));
                    marketData.lineFlag = sectionId;
                    // 包外数据

                }
                    break;
                case 5: // 中金
                {

                }

                    break;
                default:
                    SPDLOG_LOGGER_ERROR(my_logger,"没有匹配的交易所：exchange_id={}",exchange_id);
                    break;
            }


/*            // ========================== 原始字节数组 ↓↓↓↓↓↓
        // 输出原始字节数组
        for (int i = 0; i < valread; i++) {
            // 将 buffer[i] 的值以两位十六进制格式输出，并在不足两位时用 '0' 补齐
            //  使用 std::hex 设置输出为十六进制。
            //  使用 std::setw(2) 和 std::setfill('0') 确保输出宽度为两位，不足部分用 '0' 填充。
            //  将 buffer[i] 转换为整数并输出
            std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)buffer[i] << " ";
            if ((i + 1) % 40 == 0) {
                std::cout << std::endl;
            }
        }
        // 手动解析字节数组
        struct hello {
            unsigned char c1; // 占1个字节，共8位，能够容纳0到255（即0x00到0xFF）的值
            char c2; // 可能占1个(新平台)或2个(旧平台)字节
            unsigned char c3;
            unsigned char c4;
            unsigned char c5;
        };
        struct hello *hello = (struct hello *)buffer;
        std::cout << "\n前5个字节: " << hello->c1 << " " << hello->c2 << " " << hello->c3 << " " << hello->c4 << " " << hello->c5 << std::endl;

            // ========================== 原始字节数组 ↑↑↑↑↑↑↑*/
        }

/*        while(1) {
            struct epoll_event events[MAX_EVENTS];
            int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); // 阻塞等待事件
            if (num_events < 0) {
                perror("Epoll wait failed");
                break;
            }

            for (int i = 0; i < num_events; ++i) {
                if (events[i].data.fd == client_fd) {
                    // 套接字可读，调用 recvfrom()
                    ssize_t recv_len = recvfrom(client_fd, buffer, sizeof(buffer), 0,
                                                (struct sockaddr *)&client_addr, &client_len);
                    if (recv_len < 0) {
                        perror("Recvfrom failed");
                        break;
                    }

                    std::cout << "Received " << recv_len << " bytes from "
                              << inet_ntoa(client_addr.sin_addr) << ":"
                              << ntohs(client_addr.sin_port) << std::endl;
                    std::cout << "Data: " << std::string(buffer, recv_len) << std::endl;
                }
            }
        }*/

        // 关闭套接字
        close(client_fd);
        return 0;

    }

    int SocketUtils::readNetworkIfaceLine_epoll(std::string sectionId, std::chrono::system_clock::time_point startTime,
                                          ntp::IniReader* iniCfg, SafeQueue<MarketData>* data_queue, std::string debug) {

        // 从配置文件中获取配置
        std::string device = iniCfg->ReadString(sectionId.data(), "device","");
        std::string sourceIP = iniCfg->ReadString(sectionId.data(), "sourceIP","");
        std::string sourcePort = iniCfg->ReadString(sectionId.data(), "sourcePort","");
        std::string destinationIP = iniCfg->ReadString(sectionId.data(), "destinationIP","");
        int destinationPort = iniCfg->ReadInt(sectionId.data(), "destinationPort",-1);
        std::string filterStr = iniCfg->ReadString(sectionId.data(), "filterStr",""); // 抓包过滤条件

        std::string target_time_all = iniCfg->ReadString("MODE", "target_time_all","");
        int exchange_id = iniCfg->ReadInt("MODE", "exchange_id",0);

        //std::ofstream outFile("socket_out_" + sectionId + ".csv");
        std::ofstream outFile("pcap_out_epoll_" + sectionId + ".csv");

        // ======================
        int client_fd, epoll_fd;
        client_fd = socket(PF_PACKET, SOCK_RAW/*SOCK_DGRAM*/, htons(ETH_P_ALL/*ETH_P_IP*/));
        if (client_fd < 0) {
            perror("Socket creation failed");
            return 1;
        }

        int BufferSize = 1024 * 1024 * 12;
        // 设置套接字选项的 Unix 系统调用，可以添加自定义的过滤规则
        int retSet = ::setsockopt(client_fd, SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize));
        if (retSet != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
        // 设置文件描述符为非阻塞
        int i_ret = fcntl(client_fd,F_SETFL, O_NONBLOCK);  // 设置文件描述符的状态标志
        if (i_ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
        // 绑定网卡设备，使用网卡名称
        struct ifreq stIf;
        strcpy(stIf.ifr_name, device.c_str());
        int ret = ioctl(client_fd, SIOCGIFINDEX, &stIf); // ioctl 函数允许应用程序与设备驱动程序进行通信，执行各种设备特定的操作。常见的用途包括调整终端属性、获取网络接口状态等
        if (ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }

        // 设置服务器地址
        struct sockaddr_in server_address;
        memset(&server_address, 0, sizeof(server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(destinationPort);

        struct hostent *server = gethostbyname(destinationIP.c_str());
        if (server == nullptr) {
            perror("Host lookup failed ===>");
            return 1;
        }
        memcpy(&server_address.sin_addr.s_addr, server->h_addr, server->h_length);

        // 创建 epoll 实例
        epoll_fd = epoll_create1(0);
        if (epoll_fd < 0) {
            perror("Epoll create failed");
            close(client_fd);
            return EXIT_FAILURE;
        }

        // 注册 socket 到 epoll
        struct epoll_event event;
        event.events = EPOLLIN; // 监听可读事件
        event.data.fd = client_fd;
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event) < 0) {
            perror("Epoll ctl failed");
            close(client_fd);
            close(epoll_fd);
            return EXIT_FAILURE;
        }


        struct sockaddr_in server_addr, client_addr;
        socklen_t client_len = sizeof(client_addr);
        char buffer[1024];

        int pkgCount=0;
        while(1) {
            // 接收数据
            struct sockaddr_in server_addr;
            socklen_t server_len = sizeof(server_addr);
            // =============================
            struct epoll_event events[MAX_EVENTS];
            int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); // 当timeout设置为‒1时，epoll_wait调用将永远阻塞，直到某个事件发生；当timeout设置为0时，epoll_wait调用将立即返回；当timeout设置为大于0时，表示指定的毫秒
            if (num_events < 0) {
                perror("Epoll wait failed");
                break;
            }
            for (int i = 0; i < num_events; ++i) {
                if (events[i].data.fd == client_fd) {
                    // 套接字可读，调用 recvfrom()
                    ssize_t recv_len = recvfrom(client_fd, buffer, sizeof(buffer), 0,
                                                (struct sockaddr *)&client_addr, &client_len);
                    if (recv_len < 0) {
                        perror("Recvfrom failed");
                        break;
                    }

                    //std::cout << "num_events=" << num_events
                    //<< ",recv_len=" << recv_len
                    //<< std::endl;

                    // ==============================
                    // 获取纳秒级时间戳
                    auto now = std::chrono::high_resolution_clock::now();
                    auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
                            now.time_since_epoch())
                            .count();

                    switch (exchange_id) {
                        case 1: // 广期
                            // 基于时间窗口的统计 = 每3秒一个窗口，记录一次
                        {
                            pkgCount++;
                        }
                            break;
                        case 2: // 上期
                        {
                            pkgCount++;

                            MarketData marketData;
                            memset(&marketData, 0x00, sizeof(MarketData));
                            marketData.lineFlag = sectionId;
                            marketData.destinationIP = destinationIP;
                            // 包外数据

                            // 包内毫秒级时间戳
                            //marketData.snap_time = header->ts.tv_sec * 1000 + header->ts.tv_usec / 1000;
                            marketData.local_time = std::chrono::high_resolution_clock::now(); // 本地时间戳，纳秒级别

                            marketData.pkgCount = pkgCount; // 包计数器，编号从1开始

                            // 解析数据包中的数据，传递的数据尽量要少
                            //marketData.pkthdr = header; // 原始包头数据
                            //marketData.packet = packet; // 原始payload数据
                            pcap_pkthdr* pkthdr;
                            pkthdr = (pcap_pkthdr*)malloc(sizeof(pcap_pkthdr));
                            pkthdr->caplen = 0;
                            pkthdr->len = recv_len; // 长度
                            pkthdr->ts.tv_sec = timestamp / 1000000000;
                            pkthdr->ts.tv_usec = timestamp % 1000000000;
                            //std::cout << "pkgCount=" << pkgCount << ",tv_sec=" << pkthdr->ts.tv_sec << ",tv_usec=" << pkthdr->ts.tv_usec  << std::endl;
                            shfe_decode::parse_packet_shfe(pkthdr, reinterpret_cast<const u_char*>(buffer), marketData, outFile);

                            //struct my_ether_header *eth_hdr = (struct my_ether_header *)packet;
                            //std::cout << "eth_hdr->ether_type=" << eth_hdr->ether_type << std::endl;

                            //SPDLOG_LOGGER_INFO(my_logger,"{},packet_no={},time1={},time2={},snap_time={},snap_millisec={}",sectionId,marketData.packet_no,marketData.time1,marketData.time2,marketData.snap_time,marketData.snap_millisec);
                        }
                            break;
                        case 3: // 大连
                        {
                            pkgCount++; // 当前接受的总包数，包数不是连续的？？？
                        }
                            break;
                        case 4: // 郑州
                        {
                            pkgCount++; // 当前接受的总包数，包数不是连续的？？？

                            MarketData marketData;
                            memset(&marketData, 0x00, sizeof(MarketData));
                            marketData.lineFlag = sectionId;
                            // 包外数据

                        }
                            break;
                        case 5: // 中金
                        {

                        }

                            break;
                        default:
                            SPDLOG_LOGGER_ERROR(my_logger,"没有匹配的交易所：exchange_id={}",exchange_id);
                            break;
                    }
                }
            }
/*            // ========================== 原始字节数组 ↓↓↓↓↓↓
        // 输出原始字节数组
        for (int i = 0; i < valread; i++) {
            // 将 buffer[i] 的值以两位十六进制格式输出，并在不足两位时用 '0' 补齐
            //  使用 std::hex 设置输出为十六进制。
            //  使用 std::setw(2) 和 std::setfill('0') 确保输出宽度为两位，不足部分用 '0' 填充。
            //  将 buffer[i] 转换为整数并输出
            std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)buffer[i] << " ";
            if ((i + 1) % 40 == 0) {
                std::cout << std::endl;
            }
        }
        // 手动解析字节数组
        struct hello {
            unsigned char c1; // 占1个字节，共8位，能够容纳0到255（即0x00到0xFF）的值
            char c2; // 可能占1个(新平台)或2个(旧平台)字节
            unsigned char c3;
            unsigned char c4;
            unsigned char c5;
        };
        struct hello *hello = (struct hello *)buffer;
        std::cout << "\n前5个字节: " << hello->c1 << " " << hello->c2 << " " << hello->c3 << " " << hello->c4 << " " << hello->c5 << std::endl;

            // ========================== 原始字节数组 ↑↑↑↑↑↑↑*/
        }

        // 关闭套接字
        close(client_fd);
        close(epoll_fd);
        return 0;

    }

// 获取网卡的信息
    void SocketUtils::get_interface_ips() {
        struct ifaddrs *ifaddr, *ifa;
        if (getifaddrs(&ifaddr) == -1) {
            perror("getifaddrs");
            return;
        }

        for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
            if (ifa->ifa_addr == nullptr || ifa->ifa_addr->sa_family != AF_INET) {
                continue; // 跳过非 IPv4 地址
            }

            char ip[INET_ADDRSTRLEN];
            inet_ntop(AF_INET, &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, ip, INET_ADDRSTRLEN);
            std::cout << "Interface: " << ifa->ifa_name << ", IP: " << ip << std::endl;
        }

        freeifaddrs(ifaddr);
    }

/* 使用socket 实现抓包*/
    int SocketUtils::readNetwork(std::string sectionId, std::chrono::system_clock::time_point startTime, ntp::IniReader* iniCfg) {
        // 使用socket从网卡获取数据包
        // 创建套接字
        //int client_fd = socket(AF_INET, SOCK_DGRAM, 0);
        int client_fd = socket(PF_PACKET, SOCK_RAW/*SOCK_DGRAM*/, htons(ETH_P_ALL/*ETH_P_IP*/));
        if (client_fd < 0) {
            perror("Socket creation failed");
            return 1;
        }
        int BufferSize = 1024 * 1024 * 12;
        // 设置套接字选项的 Unix 系统调用，可以添加自定义的过滤规则
        int retSet = ::setsockopt(client_fd, SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize));
        if (retSet != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
        // 设置文件描述符为非阻塞
        int i_ret = fcntl(client_fd,F_SETFL, O_NONBLOCK);  // 设置文件描述符的状态标志
        if (i_ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }
/*    struct ifreq stIf; // struct ifreq 结构体用于获取网络接口的信息，如名称、索引、IP地址等
    strcpy(stIf.ifr_name, "");
    int ret = ioctl(client_fd, SIOCGIFINDEX, &stIf); // ioctl 函数允许应用程序与设备驱动程序进行通信，执行各种设备特定的操作。常见的用途包括调整终端属性、获取网络接口状态等
    if (ret < 0)
    {
        printf("SIOCGIFINDEX error\r\n");
        close(client_fd);
        return false;
    }
    else
    {
        //printf("SIOCGIFINDEX,%d\r\n", stIf.ifr_ifindex);
    }

    // 绑定 网卡
    struct sockaddr_ll stLocal = { 0 };
    stLocal.sll_family = PF_PACKET;
    stLocal.sll_ifindex = stIf.ifr_ifindex;
    stLocal.sll_protocol = htons(ETH_P_ALL);
    ret = ::bind(client_fd, (struct sockaddr*)&stLocal, sizeof(stLocal));
    if (ret == -1)
    {
        printf("bind error,%s\r\n", "");
        close(client_fd);
        return false;
    }

    //set IFF_PROMISC
    struct ifreq stIfr;
    strcpy(stIfr.ifr_name, stIf.ifr_name);
    ret = ioctl(client_fd, SIOCGIFFLAGS, &stIfr);
    if (0 > ret)
    {
        printf("SIOCGIFFLAGS error");
        close(client_fd);
        return false;
    }
    stIfr.ifr_flags |= IFF_PROMISC;//混杂模式
    //stIfr.ifr_flags &= ~IFF_PROMISC;//取消混杂模式
    ret = ioctl(client_fd, SIOCSIFFLAGS, &stIfr);
    if (0 > ret)
    {
        printf("SIOCSIFFLAGS error");
        close(client_fd);
        return false;
    }*/

/*    // 启用硬件时间戳（需网卡支持）
    int timestamping_flags = SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE;
    if (setsockopt(client_fd, SOL_SOCKET, SO_TIMESTAMPING, &timestamping_flags, sizeof(timestamping_flags)) < 0) {
        close(client_fd);
        throw std::system_error(errno, std::generic_category(), "setsockopt");
    }*/


        // 绑定网卡设备，使用端口名/_portName
        struct ifreq stIf;
        strcpy(stIf.ifr_name, "ens36");
        int ret = ioctl(client_fd, SIOCGIFINDEX, &stIf); // ioctl 函数允许应用程序与设备驱动程序进行通信，执行各种设备特定的操作。常见的用途包括调整终端属性、获取网络接口状态等
        if (ret != 0) {
            printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
            return false;
        }


        // 设置服务器地址
        struct sockaddr_in server_address;
        memset(&server_address, 0, sizeof(server_address));
        server_address.sin_family = AF_INET;
        server_address.sin_port = htons(23005);

        struct hostent *server = gethostbyname("239.27.1.1");
        if (server == nullptr) {
            perror("Host lookup failed");
            return 1;
        }
        memcpy(&server_address.sin_addr.s_addr, server->h_addr, server->h_length);

        // 发送数据
        //const char *message = "Hello from client"; // Hello from server = 17字节
        //sendto(client_fd, message, strlen(message), 0, (struct sockaddr *)&server_address, sizeof(server_address));

        char buffer[4096] = {0};
        int ii= 0;
        while(1) {
            ii++;
            // 接收数据
            struct sockaddr_in server_addr;
            socklen_t server_len = sizeof(server_addr);
            int valread = recvfrom(client_fd, buffer, 4096, 0, (struct sockaddr *)&server_addr, &server_len);
            if (valread < 0) {
                perror("Read failed ===>");
                return 1;
            }
            struct timeval tv;
            if (valread >= 0) {
                // 获取时间戳
                if (gettimeofday(&tv, NULL) != -1) {
                    printf("数据包的时间戳为(毫秒级): %ld.%06ld\n", tv.tv_sec, tv.tv_usec);
                }
            } else {
                // 错误处理
                if (errno != EAGAIN) {
                    perror("recvfrom");
                    //break;
                }
            }
            std::cout << "Message from server: " << strlen(buffer) << ", 字节长度: " << valread << ",ii=" << ii << std::endl;

            // ========================== 原始字节数组 ↓↓↓↓↓↓
            // 输出原始字节数组
            for (int i = 0; i < valread; i++) {
                // 将 buffer[i] 的值以两位十六进制格式输出，并在不足两位时用 '0' 补齐
                //  使用 std::hex 设置输出为十六进制。
                //  使用 std::setw(2) 和 std::setfill('0') 确保输出宽度为两位，不足部分用 '0' 填充。
                //  将 buffer[i] 转换为整数并输出
                std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)buffer[i] << " ";
                if ((i + 1) % 40 == 0) {
                    std::cout << std::endl;
                }
            }
/*        // 手动解析字节数组
        struct hello {
            unsigned char c1; // 占1个字节，共8位，能够容纳0到255（即0x00到0xFF）的值
            char c2; // 可能占1个(新平台)或2个(旧平台)字节
            unsigned char c3;
            unsigned char c4;
            unsigned char c5;
        };
        struct hello *hello = (struct hello *)buffer;
        std::cout << "\n前5个字节: " << hello->c1 << " " << hello->c2 << " " << hello->c3 << " " << hello->c4 << " " << hello->c5 << std::endl;*/

            // ========================== 原始字节数组 ↑↑↑↑↑↑↑
        }

        // 关闭套接字
        close(client_fd);
        return 0;
    }



    int SocketUtils::readNetwork2() {
        const char *interface_name = "ens36"; // 指定网卡名称
        const char *local_ip = "192.168.80.186"; // "239.27.1.1"; // 指定网卡的 IP 地址
        int port = 23005; //42228 23005; // 绑定的端口号

        // 创建 UDP socket
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) {
            perror("Socket creation failed");
            return EXIT_FAILURE;
        }

        // 设置 SO_BINDTODEVICE（可选）
        if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, interface_name, strlen(interface_name)) < 0) {
            perror("Setsockopt SO_BINDTODEVICE failed");
            close(sockfd);
            return EXIT_FAILURE;
        }

        // 绑定到指定网卡的 IP 地址和端口
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
        server_addr.sin_addr.s_addr = inet_addr(local_ip);

        if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
            perror("Bind failed");
            close(sockfd);
            return EXIT_FAILURE;
        }

        std::cout << "Socket bound to interface: " << interface_name << " with IP: " << local_ip << std::endl;

        // 接收数据
        char buffer[1024];
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);

        while (true) {
            ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0,
                                        (struct sockaddr *)&client_addr, &client_len);
            if (recv_len < 0) {
                perror("Recvfrom failed");
                break;
            }

            std::cout << "Received " << recv_len << " bytes from "
                      << inet_ntoa(client_addr.sin_addr) << ":"
                      << ntohs(client_addr.sin_port) << std::endl;
            std::cout << "Data: " << std::string(buffer, recv_len) << std::endl;
        }

        close(sockfd);
        return 0;
    }

// 使用socket获取组播数据
    int SocketUtils::readNetwork3() {
        const char *multicast_ip = "239.27.1.1"; // 组播 IP 地址
        const char *local_ip = "192.168.80.186";   // 指定网卡的本地 IP 地址
        int port = 42228;                         // 绑定的本地端口号

        // 创建 UDP socket
        int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (sockfd < 0) {
            perror("Socket creation failed");
            return EXIT_FAILURE;
        }

        // 绑定到指定网卡的本地 IP 和端口
        struct sockaddr_in local_addr;
        memset(&local_addr, 0, sizeof(local_addr));
        local_addr.sin_family = AF_INET;
        local_addr.sin_port = htons(port);
        local_addr.sin_addr.s_addr = inet_addr(local_ip);

        if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
            perror("Bind failed");
            close(sockfd);
            return EXIT_FAILURE;
        }

        std::cout << "Socket bound to local IP: " << local_ip << " on port: " << port << std::endl;

        // 加入组播组
        struct ip_mreq mreq;
        mreq.imr_multiaddr.s_addr = inet_addr(multicast_ip); // 组播 IP 地址
        mreq.imr_interface.s_addr = inet_addr(local_ip);     // 指定网卡的本地 IP 地址

        if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
            perror("Setsockopt IP_ADD_MEMBERSHIP failed");
            close(sockfd);
            return EXIT_FAILURE;
        }

        std::cout << "Joined multicast group: " << multicast_ip << std::endl;

        // 接收组播数据
        char buffer[1024];
        struct sockaddr_in sender_addr;
        socklen_t sender_len = sizeof(sender_addr);

        while (true) {
            ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0,
                                        (struct sockaddr *)&sender_addr, &sender_len);
            if (recv_len < 0) {
                perror("Recvfrom failed");
                break;
            }

            std::cout << "Received " << recv_len << " bytes from "
                      << inet_ntoa(sender_addr.sin_addr) << ":"
                      << ntohs(sender_addr.sin_port) << std::endl;
            std::cout << "Data: " << std::string(buffer, recv_len) << std::endl;
        }

        // 离开组播组（可选）
        setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));

        close(sockfd);
        return 0;
    }

    int SocketUtils::readNetwork4() {}

/*int SocketUtils::readNetwork4() {
    strcpy(device, "ens36");
    printf("0,InitRaw,%s\r\n", device);
    bool bRet = createRaw();
    if (bRet == 0) {
        printf("createRaw failed,%d\r\n", bRet);
        return 1;
    }
    bRet = set_non_blocking(1);
    if (bRet == 0) {
        printf("set_non_blocking,%d\r\n", bRet);
        return 1;
    }
    bRet = bindRaw(device);
    if (bRet == 0) {
        printf("0,bind failed,%d\r\n", bRet);
        return 1;
    }
    else {
        printf("0,bind,%s\r\n", device);
    }

    unsigned char Buffer[2048];
    int Length = 0;
    int Count = 0;

    IPHEADER* iph = (IPHEADER*)(Buffer + sizeof(ETHHEADER)); // 初始化
    //pDataUdp = (Zbp05Udp*)Buffer; // 完整的udp报文
    //pData = (Zbp05*)(Buffer + sizeof(ETHHEADER) + sizeof(IPHEADER) + sizeof(UDPHEADER)); // udp5档行情报文
    // 将指针 pData 指向缓冲区 Buffer 中特定位置的数据，具体位置是从 Buffer 开始，跳过以太网头（ETHHEADER）、IP 头（IPHEADER）和 UDP 头（UDPHEADER）的长度后的位置

    while (1) {
        if (!is_valid()) {
            break;
        }
        Length = recvRaw(Buffer); // 接收的字节数

        if (Length >= 60) { // tcp报头 = ip/20 + tcp/60
            if (iph->proto == 0x11) { //
                if (iph->destIP == 0xC0A80B01) { // 192.168.8.1
                    //printf("0,recv,%d\r\n", Length);
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                    Count++;
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                }

            } else if (iph->proto == 0x06) {
                if (iph->destIP == 0xC0A80B01) { // 192.168.8.1
                    //printf("0,recv,%d\r\n", Length);
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                    Count++;
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                    //printf("0,recv,%d,%d\r\n", Length, Count);
                }
            }

        }
    }

}*/

/*
// 设置 m_sock 为非阻塞状态
bool SocketUtils::set_non_blocking(const bool b) {
    int opts;
    // 复制文件描述符(F_DUPFD、F_DUPFD_CLOEXEC)；
    // 获取/设置文件描述符标志(F_GETFD、F_SETFD)；
    // 获取/设置文件状态标志(F_GETFL、F_SETFL)；
    // 获取/设置记录锁(F_GETLK、F_SETLK、F_SETLKW)；
    opts = fcntl(m_sock, F_GETFL); // 获取文件描述符的状态标志

    if (opts < 0)    {
        return false;
    }

    if (b)
        opts = (opts | O_NONBLOCK); // 非阻塞模式
    else
        opts = (opts & ~O_NONBLOCK); // 非 非阻塞模式

    int i_ret = fcntl(m_sock,
                      F_SETFL, opts);  // 设置文件描述符的状态标志
    if (i_ret < 0)    {
        return false;
    }
    {
        return true;
    }
}

// 获取原始字节流的 socket
bool SocketUtils::createRaw() {
    m_sock = socket(PF_PACKET, SOCK_RAW*/
/*SOCK_DGRAM*//*
, htons(ETH_P_ALL*/
/*ETH_P_IP*//*
));

    if (m_sock <= 0 || m_sock == 0xffffffff) {
        return false;
    }

    int BufferSize = 1024 * 1024 * 12;
    // 设置套接字选项的 Unix 系统调用，可以添加自定义的过滤规则
    int retSet = ::setsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, &BufferSize, sizeof(BufferSize));
    if (retSet != 0) {
        printf("setsockopt SO_RCVBUF failed,%d\r\n", errno);
        return false;
    }    else    {
        //socklen_t len = 4;
        //::getsockopt(m_sock, SOL_SOCKET, SO_RCVBUF, &BufferSize, &len);
        //printf("setsockopt SO_RCVBUF %d\r\n", BufferSize);
    }
    //printf("create socket,%d\r\n", m_sock);
    return true;
}

// 绑定网卡设备，使用端口名/_portName
bool SocketUtils::bindRaw(char* _portName) {
    struct ifreq stIf;
    strcpy(stIf.ifr_name, _portName);
    int ret = ioctl(m_sock, SIOCGIFINDEX, &stIf); // ioctl 函数允许应用程序与设备驱动程序进行通信，执行各种设备特定的操作。常见的用途包括调整终端属性、获取网络接口状态等
    if (ret < 0)    {
        printf("SIOCGIFINDEX error\r\n");
        close(m_sock);
        return false;
    }    else    {
        //printf("SIOCGIFINDEX,%d\r\n", stIf.ifr_ifindex);
    }

    // 绑定 网卡
    struct sockaddr_ll stLocal = { 0 };
    stLocal.sll_family = PF_PACKET;
    stLocal.sll_ifindex = stIf.ifr_ifindex;
    stLocal.sll_protocol = htons(ETH_P_ALL);
    ret = ::bind(m_sock, (struct sockaddr*)&stLocal, sizeof(stLocal));
    if (ret == -1)    {
        printf("bind error,%s\r\n", _portName);
        close(m_sock);
        return false;
    }

    //set IFF_PROMISC
    struct ifreq stIfr;
    strcpy(stIfr.ifr_name, stIf.ifr_name);
    ret = ioctl(m_sock, SIOCGIFFLAGS, &stIfr);
    if (0 > ret) {
        printf("SIOCGIFFLAGS error");
        close(m_sock);
        return false;
    }
    stIfr.ifr_flags |= IFF_PROMISC;//混杂模式
    //stIfr.ifr_flags &= ~IFF_PROMISC;//取消混杂模式
    ret = ioctl(m_sock, SIOCSIFFLAGS, &stIfr);
    if (0 > ret)    {
        printf("SIOCSIFFLAGS error");
        close(m_sock);
        return false;
    }

    memset(&SockaddrRawSend, 0, sizeof(SockaddrRawSend));
    SockaddrRawSend.sll_family = PF_PACKET;
    SockaddrRawSend.sll_ifindex = stIf.ifr_ifindex;
    SockaddrRawSend.sll_protocol = htons(ETH_P_ALL);
    SockaddrRawSend.sll_pkttype = PACKET_OUTGOING;
    SockaddrRawSend.sll_halen = 6;

    strcpy(IfName, _portName);

    return true;
}

int SocketUtils::recvRaw(unsigned char* _Buffer){
    // 与简单的 recv() 函数不同，recvfrom() 可以返回数据来源的地址信息，返回所接收的字节数
    //return ::recvfrom(m_sock, _Buffer, MAXRECV, 0, NULL, NULL); // 从套接字接收数据
    return recvfrom(m_sock, _Buffer, MAXRECV, 0, NULL, NULL); // 从套接字接收数据
}

int SocketUtils::sendRaw(unsigned char* _Buffer, int _Length){
    //return ::sendto(m_sock, _Buffer, _Length, 0, (const struct sockaddr*)&SockaddrRawSend, sizeof(SockaddrRawSend));
    return sendto(m_sock, _Buffer, _Length, 0, (const struct sockaddr*)&SockaddrRawSend, sizeof(SockaddrRawSend));
}

*/



}
